package com.softserveinc.fragments.adapter;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ArrayAdapter;

import com.softserveinc.MovieManagerApplication;
import com.softserveinc.R;
import com.softserveinc.data.MovieDataManager;
import com.softserveinc.data.MovieDataManager.PageableMovieListCallBack;
import com.softserveinc.data.help.MovieListType;
import com.softserveinc.fragments.AbstractListFragment.OnListItemClickListener;
import com.softserveinc.fragments.adapter.MovieTableAdapter.MoviePair;
import com.softserveinc.model.Movie;

public class MovieTableAdapter extends ArrayAdapter<MoviePair> implements
		MovieDataManager.MoviePosterCallBack {

	private static final int COLUMN_COUNT = 2;

	protected static final String TAG = MovieTableAdapter.class.getSimpleName();

	private final PageableMovieListCallBack pageableCallBack;

	private final MovieListType movieListType;

	private final OnScrollListener scrollListemer = new MovieListScrollListemer();

	private final MovieManagerApplication application;

	private OnListItemClickListener clickListener;

	private boolean busy = false;
	private boolean ready = true;

	public MovieTableAdapter(final Context context, final List<Movie> movies,
			final PageableMovieListCallBack pageableCallBack,
			final MovieListType movieListType) {
		super(context, 0);

		addMoviePairs(createMoviePairCollection(movies));

		this.pageableCallBack = pageableCallBack;
		this.movieListType = movieListType;

		application = (MovieManagerApplication) context.getApplicationContext();
	}

	public int size() {
		return getCount() * COLUMN_COUNT;
	}

	public void addMovies(final List<Movie> movies) {
		if (getCount() == 0) {
			addMoviePairs(createMoviePairCollection(movies));
			return;
		}

		int index = (getCount() - 1);

		MoviePair pair = getItem(index);

		if (pair.getRightMovie() == null) {

			pair.setRightMovie(movies.get(0));

			notifyDataSetChanged();

			addMoviePairs(createMoviePairCollection(movies, 1));
		} else {
			addMoviePairs(createMoviePairCollection(movies));
		}
	}

	private void addMoviePairs(final List<MoviePair> moviePairCollection) {
		for (MoviePair moviePair : moviePairCollection) {
			add(moviePair);
		}
	}

	private List<MoviePair> createMoviePairCollection(final List<Movie> movies) {
		return createMoviePairCollection(movies, 0);
	}

	private List<MoviePair> createMoviePairCollection(final List<Movie> movies,
			final int startForm) {
		final List<MoviePair> moviePairs = new ArrayList<MoviePair>();

		for (int index = startForm; index < movies.size(); index++) {
			Movie leftMovie = movies.get(index);
			Movie rightMovie = null;

			index++;

			if (index < movies.size()) {
				rightMovie = movies.get(index);
			}

			MoviePair pair = new MoviePair(leftMovie, rightMovie);

			moviePairs.add(pair);
		}

		return moviePairs;
	}

	@Override
	public View getView(final int position, final View convertView,
			final ViewGroup parent) {
		View view = convertView;

		if (view == null) {
			view = View.inflate(getContext(), R.layout.movie_data_row, null);
		}

		MoviePair pair = getItem(position);

		final Movie leftMovie = pair.getLeftMovie();
		final Movie rightMovie = pair.getRightMovie();

		MovieTableGridItem leftGridItem = (MovieTableGridItem) view
				.findViewById(R.id.item_movie_left);

		leftGridItem.setMovie(leftMovie, isBusy());

		addOnClickListener(leftMovie, leftGridItem);

		MovieTableGridItem rightGridItem = (MovieTableGridItem) view
				.findViewById(R.id.item_movie_right);

		if (rightMovie == null) {
			rightGridItem.setVisibility(View.GONE);
		} else {
			rightGridItem.setVisibility(View.VISIBLE);

			rightGridItem.setMovie(rightMovie, isBusy());

			addOnClickListener(rightMovie, rightGridItem);
		}

		setReady(true);

		return view;
	}

	private void addOnClickListener(final Movie movie,
			final MovieTableGridItem gridItem) {

		gridItem.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(final View v) {
				if (!isBusy() && isReady()) {
					clickListener.processListItemClick(movie);
				}
			}
		});
	}

	@Override
	public void posterLoaded() {
		notifyDataSetChanged();
	}

	public class MoviePair {
		private Movie leftMovie;
		private Movie rightMovie;

		public MoviePair(final Movie leftMovie, final Movie rightMovie) {
			this.leftMovie = leftMovie;
			this.rightMovie = rightMovie;
		}

		public Movie getLeftMovie() {
			return leftMovie;
		}

		public Movie getRightMovie() {
			return rightMovie;
		}

		public void setLeftMovie(final Movie leftMovie) {
			this.leftMovie = leftMovie;
		}

		public void setRightMovie(final Movie rightMovie) {
			this.rightMovie = rightMovie;
		}
	}

	public OnScrollListener getScrollListener() {
		return scrollListemer;
	}

	public OnListItemClickListener getClickListener() {
		return clickListener;
	}

	public void setClickListener(final OnListItemClickListener clickListener) {
		this.clickListener = clickListener;
	}

	public boolean isBusy() {
		return busy;
	}

	public void setBusy(final boolean busy) {
		this.busy = busy;
	}

	public boolean isReady() {
		return ready;
	}

	public void setReady(final boolean ready) {
		this.ready = ready;
	}

	private class MovieListScrollListemer implements OnScrollListener {

		private boolean nonScrolled = true;

		@Override
		public void onScrollStateChanged(final AbsListView view,
				final int scrollState) {

			switch (scrollState) {
			case SCROLL_STATE_IDLE:
				setBusy(false);

				validateImages(view);

				if (pageableCallBack != null
						&& view.getLastVisiblePosition() == getCount()) {
					loadMoreMovies(view);
				}

				break;
			case SCROLL_STATE_TOUCH_SCROLL:
				setBusy(true);
				setReady(false);

				application.getDataManager().interruptLoadingPosters(
						MovieTableAdapter.this);
				break;
			case SCROLL_STATE_FLING:
				setBusy(true);
				setReady(false);
				break;
			}
		}

		@Override
		public void onScroll(final AbsListView view,
				final int firstVisibleItem, final int visibleItemCount,
				final int totalItemCount) {
			if (nonScrolled && view.getLastVisiblePosition() > 0) {

				nonScrolled = false;

				validateImages(view);
				return;
			}
		}

		private void loadMoreMovies(final AbsListView view) {
			int lastPosition = view.getLastVisiblePosition();

			if (lastPosition * COLUMN_COUNT >= MovieDataManager.MAX_MOVIE_LIST_SIZE
					|| !application.getHardwareManager().isNetworkConnected()) {

				pageableCallBack.restrictLoading();
			} else {
				int currentPage = (lastPosition * COLUMN_COUNT)
						/ MovieDataManager.PAGE_SIZE;

				int nextPage = ++currentPage;

				Log.d(TAG, "page " + nextPage);

				application.getDataManager().manageDataForMovieList(
						pageableCallBack, movieListType, nextPage);
			}
		}

		private void validateImages(final AbsListView view) {
			List<Movie> movies = new ArrayList<Movie>();

			int first = view.getFirstVisiblePosition();
			int last = view.getLastVisiblePosition();

			for (int i = first; i <= last; i++) {
				if (i == getCount()) {
					break;
				}

				MoviePair moviePair = getItem(i);

				Movie movie = moviePair.getLeftMovie();

				if (movie.getPoster() == null || movie.getPoster().isRecycled()) {
					movies.add(movie);
				}

				movie = moviePair.getRightMovie();

				if (movie != null
						&& (movie.getPoster() == null || movie.getPoster()
								.isRecycled())) {
					movies.add(movie);
				}
			}

			application.getDataManager().manageDataForMovieListImages(movies,
					MovieTableAdapter.this);
		}
	}
}
